import { Module } from "vuex";
import { v4 as uuidv4 } from "uuid";
import { cloneDeep } from "lodash-es";
import { message } from "ant-design-vue";
import { AllComponentProps, textDefaultProps } from "fast-share-bricks";
import store, { GlobalDataProps } from "./index";
import { insertAt } from "@/utils/helper";
import { TextComponentProps, ImageComponentProps } from "@/defaultProps";
export type AllFormProps = AllComponentProps & PageProps;
export type MoveDirection = "Up" | "Down" | "Left" | "Right";
export interface ComponentData {
  // props: {
  //   [key: string]: any;
  //   // id uuid v4 生成的唯一标识
  //   // c;
  // };
  props: Partial<AllComponentProps>;
  id: string;
  // 业务组件库名称 l-text，l-image 等等
  name: "bz-text" | "bz-image" | "bz-shape";
  // 图层是否隐藏
  isHidden?: boolean;
  // 图层是否锁定
  isLocked?: boolean;
  // 图层名称
  layerName?: string;
}

export interface HistoryProps {
  id: string;
  componentId: string;
  type: "add" | "delete" | "modify";
  data: any;
  index?: number;
}
export interface EditorProps {
  components: ComponentData[];
  currentElement: string;
  page: PageData;
  // 当前被复制的组件
  copiedComponent?: ComponentData;
  // 当前操作的历史记录
  histories: HistoryProps[];
  // 当前历史记录的操作位置
  historyIndex: number;
  // 开始更新时的缓存值
  cachedOldValues: any;
  // 保存最多历史条目记录数
  maxHistoryNumber: number;
  // 数据是否有修改
  isDirty: boolean;
}
export interface PageProps {
  backgroundColor: string;
  backgroundImage: string;
  backgroundRepeat: string;
  backgroundSize: string;
  height: string;
}
// 整体页面的样式数据
export interface PageData {
  props?: PageProps;
  id?: number;
  title?: string;
  desc?: string;
  coverImg?: string;
  uuid?: string;
  setting?: { [key: string]: any };
  isTemplate?: boolean;
  isHot?: boolean;
  isNew?: boolean;
  author?: string;
  copiedCount?: number;
  status?: number;
  user?: {
    gender: string;
    nickName: string;
    picture: string;
    userName: string;
  };
}
export interface UpdateComponentData {
  key: keyof AllComponentProps | Array<keyof AllComponentProps>;
  value: string | string[];
  id: string;
  isRoot?: boolean;
}
export const testComponent: ComponentData[] = [
  {
    id: uuidv4(),
    name: "bz-text",
    layerName: "图层1",
    props: {
      ...textDefaultProps,
      text: "hello",
      fontSize: "20px",
      color: "#000000",
      lineHeight: "1",
      textAlign: "left",
      fontFamily: "",
      width: "100px",
      height: "100px",
      backgroundColor: "#efefef",
      left: "100px",
      top: "150px",
    },
  },
  // {
  //   id: uuidv4(),
  //   name: "bz-text",
  //   layerName: "图层2",
  //   props: {
  //     ...textDefaultProps,
  //     text: "captern2",
  //     fontSize: "10px",
  //     color: "red",
  //     lineHeight: "3",
  //     textAlign: "right",
  //     fontFamily: '"SimHei","STHeiti"',
  //   },
  // },
  // {
  //   id: uuidv4(),
  //   name: "bz-text",
  //   layerName: "图层3",
  //   props: {
  //     ...textDefaultProps,
  //     text: "captern3captern3captern3",
  //     fontSize: "15px",
  //     actionType: "url",
  //     url: "https://www.baidu.com",
  //     textAlign: "left",
  //     fontFamily: '"SimHei","STHeiti"',
  //     lineHeight: "1.5",
  //     color: "green",
  //   },
  // },
  // {
  //   id: uuidv4(),
  //   name: "bz-image",
  //   layerName: "图层4",
  //   props: {
  //     // src: "https://fast-share.oss-cn-shanghai.aliyuncs.com/upload-files/%E6%88%AA%E5%B1%8F2022-05-25%2011.36.22-662435.png",
  //     src: "https://img-blog.csdnimg.cn/20200612182113672.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2l0ZXllXzE5MDQ1,size_16,color_FFFFFF,t_70",
  //     actionType: "",
  //     url: "",
  //     height: "",
  //     width: "373px",
  //     paddingLeft: "0px",
  //     paddingRight: "0px",
  //     paddingTop: "0px",
  //     paddingBottom: "0px",
  //     borderStyle: "none",
  //     borderColor: "#000",
  //     borderWidth: "0",
  //     borderRadius: "0",
  //     boxShadow: "0 0 0 #000000",
  //     opacity: "1",
  //     position: "absolute",
  //     left: "0",
  //     top: "0",
  //     right: "0",
  //   },
  // },
];
const pageDefaultProps = {
  backgroundColor: "#ffffff",
  backgroundImage:
    "url('https://www.sincerecloud.com/_nuxt/img/home_banner_02.10a58af.png')",
  backgroundRepeat: "no-repeat",
  backgroundSize: "cover",
  height: "860px",
};

// 实现防抖 减少历史记录的存储
const debounceChange = (callback: (...args: any) => void, timeout = 1000) => {
  let timer = 0;
  return (...args: any) => {
    clearTimeout(timer);
    timer = window.setTimeout(() => {
      timer = 0;
      callback(...args);
    }, timeout);
  };
};

const pushHistory = (state: EditorProps, historyRecord: HistoryProps) => {
  // 判断是否移动过
  if (state.historyIndex !== -1) {
    // 移动过 有修改，将后面的 记录均删除，重新赋值
    state.histories = state.histories.slice(0, state.historyIndex);
    state.historyIndex = -1;
  }
  // 判断历史 长度
  if (state.histories.length < state.maxHistoryNumber) {
    state.histories.push(historyRecord);
  } else {
    // 先删除首项
    state.histories.shift();
    state.histories.push(historyRecord);
  }
};

const pushModifyHistory = (
  state: EditorProps,
  { key, value, id }: UpdateComponentData
) => {
  pushHistory(state, {
    id: uuidv4(),
    componentId: id || state.currentElement,
    type: "modify",
    data: { oldValue: state.cachedOldValues, newValue: value, key },
  });
  // state.histories.push({
  //   id: uuidv4(),
  //   componentId: id || state.currentElement,
  //   type: "modify",
  //   data: { oldValue: state.cachedOldValues, newValue: value, key },
  // });
  state.cachedOldValues = null;
};

const pushHistoryDebounce = debounceChange(pushModifyHistory);

const modifyHistory = (
  state: EditorProps,
  history: HistoryProps,
  type: "undo" | "redo"
) => {
  const { componentId, data } = history;
  const { key, oldValue, newValue } = data;
  const newKey = key as
    | keyof AllComponentProps
    | Array<keyof AllComponentProps>;
  const updatedComponent = state.components.find(
    (component) => component.id === componentId
  );
  if (updatedComponent) {
    if (Array.isArray(newKey)) {
      newKey.forEach((keyName, index) => {
        updatedComponent.props[keyName] =
          type === "undo" ? oldValue[index] : newValue[index];
      });
    } else {
      updatedComponent.props[newKey] = type === "undo" ? oldValue : newValue;
    }
  }
  return null;
};
const editor: Module<EditorProps, GlobalDataProps> = {
  state: {
    components: testComponent,
    currentElement: "",
    page: {
      props: pageDefaultProps,
      title: "title",
    },
    histories: [],
    historyIndex: -1,
    cachedOldValues: null,
    maxHistoryNumber: 5,
    isDirty: false,
  },
  mutations: {
    addComponent(state, component: ComponentData) {
      component.layerName = "图层" + (state.components.length + 1);
      // const newComponent: ComponentData = {
      //   id: uuidv4(),
      //   name: "bz-text",
      //   props,
      // };
      state.components.push(component);
      // 存储 history
      pushHistory(state, {
        id: uuidv4(),
        componentId: component.id,
        type: "add",
        data: cloneDeep(component),
      });
      // state.histories.push({
      //   id: uuidv4(),
      //   componentId: component.id,
      //   type: "add",
      //   data: cloneDeep(component),
      // });
    },
    setActive(state, currentElement: string) {
      state.currentElement = currentElement;
    },
    updateComponent(state, { key, value, id, isRoot }: UpdateComponentData) {
      const updatedComponent = state.components.find(
        (component) => component.id === (id || state.currentElement)
      );
      if (updatedComponent) {
        if (isRoot) {
          // https://github.com/microsoft//TypeScript/issues/31663
          // updatedComponent[key as keyof ComponentData] = value;
          (updatedComponent as any)[key as string] = value;
        } else {
          const oldValue = Array.isArray(key)
            ? key.map((key) => updatedComponent.props[key])
            : updatedComponent.props[key];
          if (!state.cachedOldValues) {
            state.cachedOldValues = oldValue;
          }
          // updatedComponent.props[key as keyof AllComponentProps];
          pushHistoryDebounce(state, { key, value, id });
          // 节流存储，防止存入多条记录
          // state.histories.push({
          //   id: uuidv4(),
          //   componentId: id || state.currentElement,
          //   type: "modify",
          //   data: {
          //     oldValue,
          //     newValue: value,
          //     key,
          //   },
          // });
          // 节流存储，防止存入多条记录
          // 开始修改值

          if (Array.isArray(key) && Array.isArray(value)) {
            key.forEach((keyName, index) => {
              updatedComponent.props[keyName] = value[index];
            });
          } else if (typeof key === "string" && typeof value === "string") {
            updatedComponent.props[key] = value;
          }
        }
      }
    },
    copyComponent(state, id: string) {
      // const currentComponent = state.components.find(
      //   (component) => component.id === id
      // );
      const currentComponent = store.getters.getElement(id);
      if (currentComponent) {
        state.copiedComponent = currentComponent;
        message.success("已拷贝当前图层", 1);
      }
    },
    pasteCopiedComponent(state) {
      if (state.copiedComponent) {
        const clone = cloneDeep(state.copiedComponent);
        clone.id = uuidv4();
        clone.layerName = clone.layerName + "副本";
        state.components.push(clone);
        message.success("已黏贴当前图层", 1);
        pushHistory(state, {
          id: uuidv4(),
          componentId: clone.id,
          type: "add",
          data: cloneDeep(clone),
        });
        // state.histories.push({
        //   id: uuidv4(),
        //   componentId: clone.id,
        //   type: "add",
        //   data: cloneDeep(clone),
        // });
      }
    },
    deleteComponent(state, id) {
      // const currentComponent = state.components.find(
      //   (component) => component.id === id
      // );
      const currentComponent = store.getters.getElement(id);
      if (currentComponent) {
        const currentIndex = state.components.findIndex(
          (component) => component.id === id
        );
        state.components = state.components.filter(
          (component) => component.id !== id
        );
        pushHistory(state, {
          id: uuidv4(),
          componentId: currentComponent.id,
          type: "delete",
          data: currentComponent,
          index: currentIndex,
        });
        // state.histories.push({
        //   id: uuidv4(),
        //   componentId: currentComponent.id,
        //   type: "delete",
        //   data: currentComponent,
        //   index: currentIndex,
        // });
        message.success("删除当前图层成功", 1);
      }
    },
    moveComponent(
      state,
      data: { direction: MoveDirection; amount: number; id: string }
    ) {
      const currentComponent = state.components.find(
        (component) => component.id === data.id
      );
      if (currentComponent) {
        const oldTop = parseInt(currentComponent.props.top || "0");
        const oldLeft = parseInt(currentComponent.props.left || "0");
        const { direction, amount } = data;
        switch (direction) {
          case "Up": {
            const newValue = oldTop - amount + "px";
            store.commit("updateComponent", {
              key: "top",
              value: newValue,
              id: data.id,
            });
            break;
          }
          case "Down": {
            const newValue = oldTop + amount + "px";
            store.commit("updateComponent", {
              key: "top",
              value: newValue,
              id: data.id,
            });
            break;
          }
          case "Left": {
            const newValue = oldLeft - amount + "px";
            store.commit("updateComponent", {
              key: "left",
              value: newValue,
              id: data.id,
            });
            break;
          }
          case "Right": {
            const newValue = oldLeft + amount + "px";
            store.commit("updateComponent", {
              key: "left",
              value: newValue,
              id: data.id,
            });
            break;
          }

          default:
            break;
        }
      }
      return null;
    },
    updatePage(state: any, { key, value }) {
      state.page.props[key as keyof PageProps] = value;
    },

    //前进操作
    undo(state) {
      if (state.historyIndex === -1) {
        state.historyIndex = state.histories.length - 1;
      } else {
        state.historyIndex--;
      }
      const history = state.histories[state.historyIndex];
      switch (history.type) {
        case "add":
          state.components = state.components.filter(
            (component) => component.id !== history.componentId
          );
          break;
        case "delete":
          state.components = insertAt(
            state.components,
            history.index as number,
            history.data
          );
          break;
        case "modify": {
          modifyHistory(state, history, "undo");
          break;
        }

        default:
          break;
      }
    },
    //后退操作
    redo(state) {
      if (state.historyIndex === -1) {
        return;
      }
      const history = state.histories[state.historyIndex];
      switch (history.type) {
        case "add":
          state.components.push(history.data);
          break;
        case "delete":
          state.components = state.components.filter(
            (component) => component.id !== history.componentId
          );
          break;
        case "modify": {
          modifyHistory(state, history, "redo");
          break;
        }
        default:
          break;
      }
      state.historyIndex++;
    },
  },
  getters: {
    getCurrentElement: (state) => {
      return state.components.find(
        (component) => component.id === state.currentElement
      );
    },
    getElement: (state) => (id: string) => {
      return state.components.find(
        (component) => component.id === (id || state.currentElement)
      );
    },
    checkUndoDisable: (state) => {
      if (state.histories.length === 0 || state.historyIndex === 0) {
        return true;
      }
      return false;
    },
    checkRedoDisable: (state) => {
      if (
        state.histories.length === 0 ||
        state.historyIndex === state.histories.length ||
        state.historyIndex === -1
      ) {
        return true;
      }
      return false;
    },
  },
};

export default editor;
